package com.wzcl.app.service.impl;

import com.alibaba.fastjson.JSON;
import com.wzcl.app.dao.model.ActivityFullCutPromotion;
import com.wzcl.app.dao.repository.ActivityFullCutPromotionRepository;
import com.wzcl.app.model.common.BusinessException;
import com.wzcl.app.model.common.CodeMsg;
import com.wzcl.app.model.common.MyPage;
import com.wzcl.app.model.common.WZCL;
import com.wzcl.app.model.dto.PromotionDto;
import com.wzcl.app.service.ActivityFullCutPromotionService;
import lombok.extern.log4j.Log4j2;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

@Log4j2
@Service
@Transactional
public class ActivityFullCutPromotionServiceImpl implements ActivityFullCutPromotionService {

    @Autowired
    private ActivityFullCutPromotionRepository repository;

    @Override
    public ActivityFullCutPromotion create(PromotionDto promotionDto) {
        ActivityFullCutPromotion fullCutPromotion = new ActivityFullCutPromotion();
        fullCutPromotion.setActivityId(promotionDto.getActivityId());
        fullCutPromotion.setOrderNo(promotionDto.getOrderNo());
        fullCutPromotion.setFullCutType(promotionDto.getFullCutType());
        fullCutPromotion.setFullPrice(new BigDecimal(promotionDto.getFullPrice()));
        fullCutPromotion.setCutPrice(new BigDecimal(promotionDto.getCutPrice()));
        return repository.save(fullCutPromotion);
    }

    @Override
    public ActivityFullCutPromotion update(PromotionDto promotionDto) {
        //校验获取
        ActivityFullCutPromotion fullCutPromotion = getAndCheckById(promotionDto);
        //修改
        fullCutPromotion.setOrderNo(promotionDto.getOrderNo());
        fullCutPromotion.setFullCutType(promotionDto.getFullCutType());
        fullCutPromotion.setFullPrice(new BigDecimal(promotionDto.getFullPrice()));
        fullCutPromotion.setCutPrice(new BigDecimal(promotionDto.getCutPrice()));
        return repository.save(fullCutPromotion);
    }

    @Override
    public ActivityFullCutPromotion getById(Integer promotionId) {
        return repository.findById(promotionId).orElse(null);
    }

    @Override
    public ActivityFullCutPromotion deleteById(Integer promotionId) {
        ActivityFullCutPromotion fullCutPromotion = getAndCheckById(promotionId);
        log.info("FullCutPromotion:{} Physical deletion", JSON.toJSONString(fullCutPromotion));
        repository.deleteById(promotionId);
        return fullCutPromotion;
    }

    @Override
    public void deleteAllByActivityId(Integer activityId) {
        repository.deleteAllByActivityId(activityId);
    }

    @Override
    public void checkValid(PromotionDto promotionDto) {
        if (promotionDto.getFullCutType() == null) {
            throw new BusinessException(CodeMsg.MUST_BE_NOT_NULL, "缺少满减类型");
        }
        if (promotionDto.getFullPrice() == null) {
            throw new BusinessException(CodeMsg.MUST_BE_NOT_NULL, "缺少对比价格");
        }
        if (promotionDto.getCutPrice() == null) {
            throw new BusinessException(CodeMsg.MUST_BE_NOT_NULL, "缺少满减值");
        }
    }

    @Override
    public void checkConflict(List<ActivityFullCutPromotion> promotionList) {
    }

    @Override
    public List<ActivityFullCutPromotion> findAllByActivityId(Integer activityId) {
        return repository.findAllByActivityIdOrderByOrderNoDesc(activityId);
    }

    @Override
    public MyPage<ActivityFullCutPromotion> findPage(PromotionDto promotionDto) {
        return new MyPage<>(repository.findAll(getSpecification(promotionDto), promotionDto.getPageable()));
    }

    @Override
    public BigDecimal computePrice(BigDecimal currentPrice, List<ActivityFullCutPromotion> promotions, Map<String,Object> condition) {
        boolean LADDER_FLAG = true;
        for (ActivityFullCutPromotion promotion : promotions){
            if (!(BigDecimal.ZERO.compareTo(currentPrice) < 0)) {
                return BigDecimal.ZERO;
            }
            if (WZCL.ACTIVITY_FULL_CUT_TYPE.FULL_CUT.equals(promotion.getFullCutType())) {
                if (currentPrice.compareTo(promotion.getFullPrice()) >= 0) {
                    //满减
                    currentPrice = compute(currentPrice, WZCL.OPERATOR_RULE.SUBTRACT, promotion.getCutPrice());
                }
            } else if (WZCL.ACTIVITY_FULL_CUT_TYPE.EVERY_FULL_CUT.equals(promotion.getFullCutType())) {
                int times = compute(currentPrice, WZCL.OPERATOR_RULE.DIVIDE, promotion.getFullPrice()).intValue();
                if (times > 0) {
                    //满减额度
                    BigDecimal value = compute(promotion.getCutPrice(), WZCL.OPERATOR_RULE.MULTIPLY, new BigDecimal(times));
                    currentPrice = compute(currentPrice, WZCL.OPERATOR_RULE.SUBTRACT, value);
                }
            } else if (WZCL.ACTIVITY_FULL_CUT_TYPE.LADDER_FULL_CUT.equals(promotion.getFullCutType())) {
                if (LADDER_FLAG && currentPrice.compareTo(promotion.getFullPrice()) >= 0) {
                    //梯度减
                    LADDER_FLAG = false;
                    currentPrice = compute(currentPrice, WZCL.OPERATOR_RULE.SUBTRACT, promotion.getCutPrice());
                }
            }
        }
        return currentPrice.setScale(2, BigDecimal.ROUND_DOWN);
    }


    @Override
    public ActivityFullCutPromotion getAndCheckById(Integer id) {
        if (id == null) {
            throw new BusinessException(CodeMsg.MUST_BE_NOT_NULL, "缺少满减活动id");
        }
        ActivityFullCutPromotion fullCutPromotion = getById(id);
        if (fullCutPromotion == null) {
            throw new BusinessException(CodeMsg.FULL_CUT_PROMOTION_NOT_EXIST);
        }
        return fullCutPromotion;
    }

    public Specification<ActivityFullCutPromotion> getSpecification(PromotionDto promotionDto) {
        return new Specification<ActivityFullCutPromotion>() {
            @Override
            public Predicate toPredicate(Root<ActivityFullCutPromotion> root, CriteriaQuery<?> criteriaQuery, CriteriaBuilder criteriaBuilder) {
                List<Predicate> predicates = new ArrayList<Predicate>();
                if (promotionDto.getActivityId() != null) {
                    predicates.add(criteriaBuilder.equal(root.get("activityId"), promotionDto.getActivityId()));
                }
                if (promotionDto.getFullCutType() != null) {
                    predicates.add(criteriaBuilder.equal(root.get("fullCutType"), promotionDto.getFullCutType()));
                }
                return criteriaBuilder.and(predicates.toArray(new Predicate[predicates.size()]));
            }
        };
    }

}
